<?php
class Comet {
	private $fd;
	private $user;
	
	private $host;
	private $port;
	private $timeout;
	
	const MSGTYPE_RECV = "RECV";
	const MSGTYPE_SEND = "SEND";
	const MSGTYPE_DEL = "DEL";
	
	
	public function __construct($host, $port, $timeout = 20) {
		$this->host = $host;
		$this->port = $port;
		$this->timeout = $timeout;
	
		$this->fd = NULL;	
	}
	
	public function recv($user) {
//		sleep(3);
		$this->_connect();
		$msgs = $this->_package(array(Comet::MSGTYPE_RECV, $user));
		$this->_send($msgs);
		$res = $this->_recv();
		$this->_close();
		return $res;
	}

	public function send($user, $msg) {
		$this->_connect();
		$msgs = $this->_package(array(Comet::MSGTYPE_SEND, $user, $msg));
		// echo "/* send $msgs */";
		$this->_send($msgs);
		$this->_close();
	}
	
	public function hasUser($user) {
		// TODO
		// return {bool};	
	}
	
	public function delUser($user) {
		$this->_connect();
		$msgs = $this->_package(array(Comet::MSGTYPE_DEL, $user));
		$this->_send($msgs);
		$this->_close();
	}
	
	private function _connect() {
		// $t = time();
		@$this->fd = @fsockopen($this->host, $this->port, $errno, $error, $this->timeout);
		if(!$this->fd) {
			$this->_error("fsockopen error: " . $errno . ", " . $error);
			exit(1) ;
		}
		// echo '/*connet cost: ' . (time() - $t) . 'ms */';
	}
	
	private function _package($blocks) {
		if(!is_array($blocks)) $blocks = array($blocks);
		// set blocks count
		$res = $this->_int2byte(count($blocks));
		
		// for each block
		foreach($blocks as $block) {
			$res .= $this->_int2byte(strlen($block)) . $block;
		}
		
		return $res;
	}
	
	private function _send($msg) {
		if($this->fd == NULL) {
			$this->_error("cannot send msg, 'Cause fd is null");	
		}
		$msg = $this->_int2byte(strlen($msg)) . $msg;
		fputs($this->fd, $msg);
	}
	
	private function _recv() {
		$res = "";
		while(!feof($this->fd)) {
			$res .= fgets($this->fd);	
		}
		return $res;
	}
	
	private function _close() {
		fclose($this->fd);
		$this->fd = NULL;	
	}
	
	private function _int2byte($val) {
		$str = "\0\0\0\0";
		/*
		$str{0} = chr(($val & 0x000000FF) >> 0);
		$str{1} = chr(($val & 0x0000FF00) >> 8);
		$str{2} = chr(($val & 0x00FF0000) >> 16);
		$str{3} = chr(($val & 0xFF000000) >> 24);
		*/
		$str{0} = chr($val >>  0 & 0xFF);
		$str{1} = chr($val >>  8 & 0xFF);
		$str{2} = chr($val >> 16 & 0xFF);
		$str{3} = chr($val >> 24 & 0xFF);
		return $str;
	}

	private function _error($msg) {
		echo "<b>ERROR</b> " . $msg;
		die();
	}
};

?>
